/*****************************************************************************
 * Copyright (c) 2022, Nations Technologies Inc.
 *
 * All rights reserved.
 * ****************************************************************************
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Nations' name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************/

/**
 * @file main.c
 * @author Nations
 * @version V1.2.2
 *
 * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
 */
#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include "my_gpio.h"


/**
 * @brief  Configures LED GPIO.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
void gpio_output_cfg(GPIO_Module* GPIOx, uint16_t Pin)
{
    GPIO_InitType GPIO_InitStructure;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    /* Enable the GPIO Clock */
    if (GPIOx == GPIOA){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    }
    else if (GPIOx == GPIOB){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
    }
    else if (GPIOx == GPIOC){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
    }
    else{
        if (GPIOx == GPIOD){
            RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE);
        }
    }
    /* Configure the GPIO pin */
    if (Pin <= GPIO_PIN_ALL){
        GPIO_InitStruct(&GPIO_InitStructure);
        GPIO_InitStructure.Pin        = Pin;
        GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
        GPIO_InitStructure.GPIO_Pull    = GPIO_No_Pull;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
    }
}


/**
 * @brief  Configures LED GPIO.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 *          GPIO_PuPdType:  GPIO_No_Pull = 0x00000000
 *                          GPIO_Pull_Up = 0x00000001;
 *                          GPIO_Pull_Down = 0x00000002;
 */
void gpio_input_cfg(GPIO_Module* GPIOx, uint16_t Pin, GPIO_PuPdType pull_up_down_mode)
{
    GPIO_InitType GPIO_InitStructure;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

    /* Enable the GPIO Clock */
    if (GPIOx == GPIOA){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    }
    else if (GPIOx == GPIOB){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
    }
    else if (GPIOx == GPIOC){
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
    }
    else{
        if (GPIOx == GPIOD){
            RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE);
        }
    }
    /* Configure the GPIO pin */
    if (Pin <= GPIO_PIN_ALL){
        GPIO_InitStruct(&GPIO_InitStructure);
        GPIO_InitStructure.Pin        = Pin;
        GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
        GPIO_InitStructure.GPIO_Pull    = pull_up_down_mode;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Input;
        GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
    }
}

/**
 * @brief  Configures LED GPIO.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
void fast_gpio_output_cfg(GPIO_Module* GPIOx, uint16_t Pin)
{
    uint32_t pinpos = 0x00U;
    uint32_t tmp = 0x00U,tmpregister=0x00U;
    uint32_t position = 0x00U;

    // /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
    tmpregister = GPIOx->PMODE;
    //  tmp = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);    //GPIO_Mode_Input
    
    while(((Pin)>>position) != 0){
        position++;
    }

    pinpos = position * 2U;
    tmp = ((uint32_t)GPIO_Mode_Out_PP) & ((uint32_t)0x0F);
    tmpregister &= ~(((uint32_t)0x03) << pinpos);
    tmpregister |=( tmp << pinpos);
    GPIOx->PMODE = tmpregister;
}

/*********
 * 高组态，快速配置
 * 
 * ****/
void fast_gpio_input_high_cfg(GPIO_Module* GPIOx, uint16_t Pin)
{

    uint32_t pinpos = 0x00U;
    uint32_t tmp = 0x00U,tmpregister=0x00U;
    uint32_t position = 0x00U;

    // /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
    tmpregister = GPIOx->PMODE;
    //  tmp = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);    //GPIO_Mode_Input
    
    while(((Pin)>>position) != 0){
        position++;
    }

    pinpos = position * 2U;
    tmp = ((uint32_t)GPIO_Mode_Input) & ((uint32_t)0x0F);
    tmpregister &= ~(((uint32_t)0x03) << pinpos);
    tmpregister |=( tmp << pinpos);
    GPIOx->PMODE = tmpregister;
}


/**
 * @brief  Turns selected Led on as output low level.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
//void LedOn(GPIO_Module* GPIOx, uint16_t Pin)
void set_pin_high(GPIO_Module* GPIOx, uint16_t Pin)
{
    GPIOx->PBSC = Pin;
}
/**
 * @brief  Turns selected Led Off as output high level.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
//void LedOff(GPIO_Module* GPIOx, uint16_t Pin)
void set_pin_low(GPIO_Module* GPIOx, uint16_t Pin)
{
    GPIOx->PBC = Pin;
}
/**
 * @brief  Turns selected Led on or off.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be one of the following values:
 * 	@arg GPIO_PIN_0~GPIO_PIN_15: set related pin on
 *   	@arg (GPIO_PIN_0<<16)~(GPIO_PIN_15<<16): clear related pin off
 */

/**
 * @brief  Toggles the selected Led.
 * @param GPIOx x can be A to G to select the GPIO port.
 * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15.
 */
//void LedBlink(GPIO_Module* GPIOx, uint16_t Pin)
void set_pin_tirrgle(GPIO_Module* GPIOx, uint16_t Pin)
{
    GPIOx->POD ^= Pin;
}


